New serverless pattern - lambda-durable-agentcore-springai-sam-java - #3264
Open
parasjain01 wants to merge 1 commit into
Open
Conversation
Human-in-the-loop AI review with AWS Lambda durable functions and Amazon Bedrock AgentCore, in Java. A Lambda durable function orchestrates a Spring AI agent hosted on AgentCore Runtime. The agent drafts a summary of a submitted document, the workflow suspends at a callback until a human approves or rejects it, then resumes and asks the agent for a final version if approved. No compute is billed while suspended, and the completed analyze step is served from its checkpoint on resume rather than re-invoking the model. Two services: Lambda and AgentCore. Workflow state - step results, the pending callback and the handler's return value - is checkpointed by the durable execution service and read back with get-durable-execution and get-durable-execution-history, so there is no table to provision. Submission and approval are both driven from the AWS CLI. The agent ships as an ARM64 container image because AgentCore hosts source code directly only for Python and Node runtimes; scripts/build-agent-image.sh builds and pushes it. The spring-ai-agentcore-runtime-starter auto-configures the POST /invocations and GET /ping endpoints AgentCore requires, so the agent is a single method annotated with @AgentCoreInvocation. Includes unit tests using the durable execution SDK's in-memory runner covering the approve, reject and timeout paths, and asserting that replay skips completed steps instead of calling the agent again. Verified end to end on AWS: the AgentCore runtime reaches READY, both agent calls succeed against Bedrock, and analyze-document records exactly one StepStarted across two InvocationCompleted events.
Contributor
Author
|
Submission issue: #3265 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Human-in-the-loop AI review with AWS Lambda durable functions and Amazon Bedrock AgentCore, in Java.
A Lambda durable function orchestrates a Spring AI agent hosted on AgentCore Runtime. The agent drafts a summary of a submitted document and flags what a reviewer should verify. The workflow then suspends at a callback until a human approves or rejects, and on approval asks the agent for a final version that folds in the reviewer's comments. No compute is billed while suspended, and the completed analyze step is served from its checkpoint on resume rather than re-invoking the model.
Two AWS services: Lambda and Amazon Bedrock AgentCore.
Workflow state — step results, the pending callback, and the handler's return value — is checkpointed by the durable execution service and read back with
get-durable-executionandget-durable-execution-history, so the pattern provisions no database. Submission and approval are both driven from the AWS CLI.Why this is useful
Agentic workflows tend to need a human somewhere in the loop, and that turns out to be awkward to build: the workflow has to wait an unbounded amount of time for a person, without holding an execution open or paying for idle compute, and without re-running the expensive model call every time it wakes up. This pattern shows the whole shape end to end, so a reader can take three specific things from it:
How to pause a workflow for a person, in Java.
waitForCallbacksuspends the execution and resumes it when a decision arrives. The pattern shows the Java API for it, including details that are easy to get wrong - operation names are mandatory and must be stable across deployments,WaitForCallbackConfignests aCallbackConfigrather than taking a timeout directly, and the execution timeout has to exceed the callback timeout or the workflow expires while still waiting.How to avoid paying twice for an agent call. Because the callback resumes into a fresh invocation that replays the handler from the top, a naive implementation re-invokes the model on every resume. The pattern shows what makes replay skip completed work, and the unit tests assert it rather than just describing it.
How to run a Java agent on AgentCore, and call it from Lambda. AgentCore hosts source code directly only for Python and Node, so a Java agent has to be an ARM64 container - the pattern includes the build script and the CloudFormation for it. It also covers two things the SDK does not make obvious:
InvokeAgentRuntimeResponsehas nopayload()accessor because the body is streamed, and reusing oneruntimeSessionIdacross both calls is what lets the agent keep its earlier turn in context across the approval gate.For readers weighing modelling choices, it also takes a position on two that caused real bugs while building it: approve and reject are both callback successes carrying the verdict as data, with failure reserved for "no decision could be obtained"; and the result keeps
outcomeseparate fromdecisionso "the reviewer said no" is never confused with "nobody answered".It sits alongside
lambda-durable-bedrock-agentcore-async, which pairs durable functions with AgentCore but useswaitForCallbackas a machine-to-machine rendezvous with no human step. The two are complementary: that one shows an async agent callback, this one a synchronous agent step behind a human gate.A note on dependencies
The agent uses
spring-ai-agentcore-runtime-starter, which auto-configures thePOST /invocationsandGET /pingendpoints AgentCore requires. It is a Spring AI Community project underorg.springaicommunity, published to Maven Central and Apache-2.0 licensed - not an official Spring AI or AWS module - and it requires Spring Boot 4.1 or later. Flagging it in case that matters for inclusion. The README says the same, and documents how to write the two endpoints by hand instead if a reader would rather not take the dependency.Testing
mvn testinorchestrator/runs 4 unit tests against the durable execution SDK's in-memory runner, covering the approve, reject and timeout paths, and asserting that replay skips completed steps rather than calling the agent again. No AWS account required.READY, both agent calls succeed against Bedrock, andanalyze-documentrecords exactly oneStepStartedacross twoInvocationCompletedevents. Approve and reject paths both confirmed, including thatfinalize-documentis skipped on rejection.sam validate --lint,sam buildand the repo'sscripts/validate.jsschema validator all pass.Checklist
README.md,example-pattern.jsonandtemplate.yamlpresent, based on_pattern-model{username}-feature-{description}The ServerlessLand URL placeholder in the README is left as
<< Add the live URL here >>pending publication.